#pragma once

#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <set>

#include "Log.hpp"
#include "InetAddr.hpp"

using namespace log_ns;

class Command
{
public:
    Command()
    {
        _safe_command.insert("ls");
        _safe_command.insert("pwd");
        _safe_command.insert("which");
        _safe_command.insert("touch");
        _safe_command.insert("whoami");
    }
    ~Command() {}
    // 检查指令安全
    bool IsSafe(const std::string &strcmd)
    {
        for (auto &cmd : _safe_command)
        {
            if (strncmp(cmd.c_str(), strcmd.c_str(), cmd.size()) == 0)
                return true;
        }
        return false;
    }
    std::string Excute(const std::string &strcmd)
    {
        if (!IsSafe(strcmd))
            return "Unsafe!";

        std::string result;
        FILE *fp = popen(strcmd.c_str(), "r");
        if (fp)
        {
            char line[1024];
            while (fgets(line, sizeof(line), fp))
            {
                result += line;
            }
            return result;
        }
        return "Excute error!";
    }
    void HandlerCommand(int sockfd, InetAddr addr)
    {
        while (1)
        {
            // 5.接收客户端发的信息
            char commandbuf[1024];
            int n = ::recv(sockfd, commandbuf, sizeof(commandbuf) - 1, 0); // 有问题？？
            if (n > 0)
            {
                // 读取成功
                commandbuf[n] = 0;
                LOG(INFO, "get message from client [%s:%d], message: %s\n", addr.Ip().c_str(), addr.Port(), commandbuf);

                std::string result = Excute(commandbuf);

                // 发回给客户端
                ::send(sockfd, result.c_str(), result.size(), 0);
            }
            else if (n == 0)
            {
                // 在IO文件里，读到0，表示读到了结尾
                // 但是网络里， 表示客户端结束
                LOG(INFO, "client [%s:%d] quit!\n", addr.Ip().c_str(), addr.Port());
                break;
            }
            else
            {
                // 读取错误
                LOG(INFO, "read error: [%s:%d]\n", addr.Ip().c_str(), addr.Port());
                break;
            }
        }
    }

private:
    std::set<std::string> _safe_command;
};